#ifndef __M_HOST_H__
#define __M_HOST_H__
#include"mq_binding.hpp"
#include"mq_exchanger.hpp"
#include"mq_message.hpp"
#include"mq_queue.hpp"

namespace mq{
    
    class Virtualhost{
        public:
            using ptr = std::shared_ptr<Virtualhost>;
            Virtualhost(const std::string& hname,const std::string& basedir,const std::string& dbfile)
            :_hostname(hname),
            _exchangesmp(std::make_shared<ExchangeManager>(dbfile)),
            _queuesmp(std::make_shared<MsgQueueManager>(dbfile)),
            _bindsmp(std::make_shared<BindingManager>(dbfile)),
            _msgsmp(std::make_shared<MessageManager>(basedir))
            {
                //todo 恢复queue的内容
               MsgqueueMap mqps = _queuesmp->allQueue();
               for(auto& mq :mqps){
                    _msgsmp->initQMessage(mq.first);
               }
            }

            bool declareExchange(const std::string& ename,ExchangeType type,bool durable,bool auto_delete,const google::protobuf::Map<std::string,std::string>& args)
            {
                return _exchangesmp->declare(ename,type,durable,auto_delete,args);
            }
            void deleteExchange(const std::string& ename){
                _bindsmp->removeExchangeBinding(ename);
                _exchangesmp->deleteExchange(ename);
            }
            Exchange::ptr getExchange(const std::string& ename){
                return _exchangesmp->select(ename);
            }

            bool bind(const std::string& ename,const std::string& qname,const std::string& key){
                //找exchange 和 queue 看看他们是不是 都是durable的
                Exchange::ptr ep = _exchangesmp->select(ename);
                if(ep.get() == nullptr){
                    LOG_ERRORM("bind false %s exchange not exists..",ename.c_str());
                    return false;
                }                
                MsgQueue::ptr mqp = _queuesmp->select(qname);
                if(mqp.get() == nullptr){
                    LOG_ERRORM("bind false %s msgqueue not exists..",qname.c_str());
                    return false;
                }
                
                return _bindsmp->bind(ename,qname,key,ep->durable && mqp->durable);
            }
            void unBind(const std::string& ename,const std::string& qname){
                _bindsmp->unBind(ename,qname);
            }
            MsgQueueBindMap exchangeBings(const std::string& ename){
                return _bindsmp->getExchangeBinding(ename);
            }

            bool declareQueue(const std::string& qname,bool qdurable,bool qexclusive,bool qauto_delete,const google::protobuf::Map<std::string,std::string>& qargs)
            {
                //消息保存句柄
                _msgsmp->initQMessage(qname);
                return _queuesmp->declare(qname,qdurable,qexclusive,qdurable,qargs);
            }

            void deleteQueue(const std::string& qname){
                _msgsmp->destroyQMessage(qname);
                _queuesmp->deleteMsgQueue(qname);
                _bindsmp->removeMsgQueueBinding(qname);
            }
            bool existsQueue(const std::string& qname){
                return _queuesmp->exists(qname);
            }
            bool basicPublish(const std::string& qname,BasicProperty* bp,const std::string& body)
            {
                //从msgqueue中找队列
                MsgQueue::ptr mqp = _queuesmp->select(qname);
                if(mqp.get() == nullptr){
                    LOG_ERRORM("basicPublish false %s msgqueue not exists..",qname.c_str());
                    return false;
                }
                //获取消息//判持久
                return _msgsmp->insert(qname,bp,body,mqp->durable);
            }

            MqMessagePtr consume(const std::string& qname){
                return _msgsmp->front(qname);
            }
            void basicAck(const std::string& qname, const std::string& msg_id){
                return _msgsmp->ack(qname,msg_id);
            }
            
            void clear(){
                _bindsmp->clear();
                _exchangesmp->clear();
                _msgsmp->clear();
                _queuesmp->clear();
                _hostname.clear();
            }
        private:
            std::string _hostname;
            BindingManager::ptr _bindsmp;
            ExchangeManager::ptr _exchangesmp;
            MessageManager::ptr _msgsmp;
            MsgQueueManager::ptr _queuesmp;
    };

}

#endif